隨著功能逐漸完善,產品目前已經具備了完整的計時與任務管理能力。
接下來,為了讓更多不同語言的使用者也能無縫使用,要在 Header 加入多國語系切換選單,支援 繁體中文 (zh-TW)、英文 (en)、日文 (ja) 三種語言。
在不使用複雜前端框架(如 React-i18next 或 Vue-i18n)的前提下,用 Vanilla JS 實作出乾淨、高效的多國語系機制:
JSON / Object 字典檔:定義每一種語言對應的文字對照表(Dictionary)。
data-i18n 屬性標記:在 HTML 標籤上加上 data-i18n="key",方便 JS 自動掃描並替換文字。
語系切換器(Language Switcher):在 Header 放入 <select>,讓使用者隨時切換。
狀態持久化:將使用者的語系偏好儲存在 localStorage,下次開啟頁面時自動載入。
i18n.js)首先建立一個字典物件,將介面上常用的固定文字統一管理:
const translations = {
'zh-TW': {
appName: '任務計時器',
startTimer: '開始計時',
pauseTimer: '暫停',
resumeTimer: '繼續',
stopTimer: '結束並儲存',
subtaskNotStarted: '未開始',
subtaskInProgress: '進行中',
subtaskCompleted: '已完成',
idleAlertTitle: '閒置提醒',
offlineNotice: '目前處於離線狀態,您的資料仍會安全儲存在本地!'
},
'en': {
appName: 'TaskTimer',
startTimer: 'Start',
pauseTimer: 'Pause',
resumeTimer: 'Resume',
stopTimer: 'Stop & Save',
subtaskNotStarted: 'Not Started',
subtaskInProgress: 'In Progress',
subtaskCompleted: 'Completed',
idleAlertTitle: 'Idle Alert',
offlineNotice: 'You are currently offline. Your data is stored locally!'
},
'ja': {
appName: 'TaskTimer',
startTimer: '開始',
pauseTimer: '一時停止',
resumeTimer: '再開',
stopTimer: '終了して保存',
subtaskNotStarted: '未着手',
subtaskInProgress: '進行中',
subtaskCompleted: '完了',
idleAlertTitle: '無操作警告',
offlineNotice: '現在オフラインです。データはローカルに保存されます!'
}
};
在 Header 區域加入語系切換的 <select> 選單:
<div class="d-flex align-items-center">
<!-- 語系切換選單 -->
<select
id="languageSelect"
class="form-select form-select-sm border-secondary-subtle rounded-pill"
style="width: auto; cursor: pointer;"
onchange="changeLanguage(this.value)"
>
<option value="zh-TW">繁體中文</option>
<option value="en">English</option>
<option value="ja">日本語</option>
</select>
</div
透過 changeLanguage() 函式更新畫面上的文字,並將偏好記錄在 localStorage:
// 預設語系:優先讀取 localStorage,若無則讀取瀏覽器預設語系,最後退回繁體中文
let currentLang = localStorage.getItem('app_lang') || navigator.language || 'zh-TW';
// 初始化時校正語系名稱(例如 en-US 轉成 en)
if (!translations[currentLang]) {
if (currentLang.startsWith('en')) currentLang = 'en';
else if (currentLang.startsWith('ja')) currentLang = 'ja';
else currentLang = 'zh-TW';
}
function changeLanguage(lang) {
if (!translations[lang]) return;
currentLang = lang;
localStorage.setItem('app_lang', lang);
// 1. 更新有 data-i18n 屬性的靜態 HTML 文字
document.querySelectorAll('[data-i18n]').forEach(element => {
const key = element.getAttribute('data-i18n');
if (translations[lang][key]) {
element.textContent = translations[lang][key];
}
});
// 2. 重新渲染動態產生的 UI(如任務清單與子任務狀態選單)
renderTaskAccordion();
// 3. 更新 Header 下拉選單本身的選取狀態
document.getElementById('languageSelect').value = lang;
}
// 頁面載入後自動套用語系
document.addEventListener('DOMContentLoaded', () => {
changeLanguage(currentLang);
});

加上 i18n 多國語系後,不再受限於單一語言,不論是繁體中文、英文還是日文使用者,都能享有一致的介面體驗。同時透過 localStorage 記憶使用者的選擇,讓使用者在每次開啟系統時都保有極佳的連續性。